package cn.fastoo.web.api.controller.user;

import cn.fastoo.common.cache.PhoneBlackListCache;
import cn.fastoo.common.cache.Price;
import cn.fastoo.common.dao.*;
import cn.fastoo.common.entity.*;
import cn.fastoo.common.sampleframe.SFBeanUtils;
import cn.fastoo.common.sampleframe.dto.JsonResult;
import cn.fastoo.common.sampleframe.search.Search;
import cn.fastoo.service.JdbcTemplateService;
import cn.fastoo.service.SmsrecordService;
import cn.fastoo.common.utils.*;
import cn.fastoo.utils.ConfigProps;
import cn.fastoo.web.dto.BatchDto;
import cn.fastoo.web.dto.SmsrecordDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Strings;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by hp on 2017/7/31.
 */

@Controller
@RequestMapping("/v1/admin")
public class SendController {

    private static Logger logger = LoggerFactory.getLogger(SendController.class);

    @Autowired
    private UserBaseDao userBaseDao;
    @Autowired
    private BatchDao batchDao;
    @Autowired
    private CountryDictDao countryDictDao;
    @Autowired
    private SmsrecordService smsrecordService;
    @Autowired
    private SmsrecordDao smsrecordDao;
    @Autowired
    private FastooMtDetailDao fastooMtDetailDao;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private JdbcTemplateService jdbcTemplateService;
    @Autowired
    private UserAccountDao userAccountDao;

    /**
     * 提交批量发送
     */
    @RequestMapping(value = "batch/submit")
    @ResponseBody
    public String batchSubmit(UserBase userBase,String selectApiKey,String batchName,  String das,String msg, String timing) {
        //1、判断参数是否合法
        if (StringUtils.isBlank(das)||StringUtils.isBlank(selectApiKey)||StringUtils.isBlank(batchName)||StringUtils.isBlank(msg)) {
            return JsonResult.create(400,"非法访问");
        }
        UserAccount userAccount = userAccountDao.findOne(new Search().addSearchFilter("EQ_apiKey",selectApiKey));
        if (userAccount==null) {
            return JsonResult.create(400,"非法访问");
        }

        //2、过滤无效号码，并统计所需费用
        // 输入号码
        if (StringUtils.isNotBlank(das)) {
            // 输入的号码加入到导入号码中
            das = filterDas(das);
        }

        //黑名单过滤
        PhoneBlackListCache phoneBlackListCache = new PhoneBlackListCache(jdbcTemplate,userBase.getId(),300);//5分钟
        List<String> phoneBlackList = (List<String>)phoneBlackListCache.get();
        das = filterBlackList(phoneBlackList, das);


        if (das.trim()=="") {
            return JsonResult.create(201,"没有可发送号码(请检查号码是否在黑名单里)");
        }


        //若有国内号码，判断apiKey是否有签名,1存在0不存在国内号码
        String signName = "";
        if (isHaveCnDa(das)) {
            if (userAccount.getSignStatus() == 1) {
                signName = userAccount.getSignName();
            } else {
                return JsonResult.create(202,"发送国内号码，签名未审核的通过");
            }
        }


        //过滤无效号码，是否含有国内号码，统计费用，并记录计费条数
        Map<String,Object> map = getFee(das,msg,selectApiKey,signName);
        das = map.get("das").toString(); //号码字符串
        Double fee = Double.valueOf(map.get("fee").toString()); //总金额
        Integer dasize = Integer.valueOf(map.get("dasize").toString()); //号码个数
        Integer totalFeeNum = Integer.valueOf(map.get("totalFeeNum").toString()); //总计费条数

        if (das.trim()=="") {
            return JsonResult.create(201,"没有可发送号码(无效号码)");
        }

        //3、金额是否不足提醒
        if (userBase.getBalance()<fee) {
            return JsonResult.create(200,"金额不足");
        }

        //4、保存计划到redis
        smsrecordService.saveBatchToRedis(userBase,selectApiKey,signName, batchName,das,msg,timing,dasize,totalFeeNum);
        logger.info("end batch submit");
        return JsonResult.success("提交成功");
    }

    private boolean isHaveCnDa(String das) {
        boolean haveCnDa = false;
        String[] dasAttr = das.split(",");
        for (String da : dasAttr) {
            String nameshort = PhoneNumberUtils.getCountryCode(da);
            if (StringUtils.isNotBlank(nameshort)) {
                if ("CN".equals(nameshort)) {
                    haveCnDa = true;
                    break;
                }
            }
        }
        return haveCnDa;
    }

    private Map<String,Object> getFee(String mobiles,String msg,String apiKey,String signName) {
        Map<String,Object> map = new HashMap<String, Object>();
        String das = "";
        Double fee = 0D;
        Integer dasize = 0;
        Integer totalFeeNum = 0;//总计费条数


        String[] dasAttr = mobiles.split(",");
        for (String da : dasAttr) {
            String nameshort = PhoneNumberUtils.getCountryCode(da);
            if (StringUtils.isNotBlank(nameshort)) {
                das = das == "" ? da : das +","+ da;
                dasize++;
                //计算短信计费条数
                Integer smsize = MessageHelper.getSmsLength(msg,nameshort,signName);
                totalFeeNum = totalFeeNum + smsize;
                Price price = PriceUtil.load(jdbcTemplate, apiKey, nameshort);
                Double perprice = BigDecimalUtil.mul(price.getMtPrice(), smsize);
                fee = BigDecimalUtil.add(fee, perprice);
            }
        }
        map.put("das",das);
        map.put("fee",fee);
        map.put("dasize",dasize);
        map.put("totalFeeNum",totalFeeNum);
        return map;
    }

    private String filterBlackList(List<String> phoneBlackList, String mobiles) {
        String das = "";
        String[] dasAttr = mobiles.split(",");
        for (String da : dasAttr) {
            if (!isPhoneBlackList(phoneBlackList,da)) {
                das = das == "" ? da : das +","+ da;
            }
        }
        return das;
    }

    private boolean isPhoneBlackList(List<String> phoneBlackList, String da) {
        if (phoneBlackList.size() > 0) {
            for (String phone : phoneBlackList) {
                if (phone.equals(da)) {
                    return true;
                }
            }
        }
        return false;
    }

    //简单过滤非法号码
    private String filterDas(String mobiles) {
        String das = "";
        Pattern pattern = Pattern.compile("^\\d+$");
        String[] mobilesArr = mobiles.split(",");
        for (int i = 0; i < mobilesArr.length; i++) {
            String mobilestr = mobilesArr[i];
            Matcher mc = pattern.matcher(mobilestr);
            if (mobilestr.trim() == "" || mc.matches() == false) {
            } else {
                das = das == "" ? mobilestr : das +","+ mobilestr;
            }
        }
        return das;
    }

    @RequestMapping(value = "batch")
    @ResponseBody
    public String batch(UserBase userBase,Integer pageNo,String batchName, String submitTime){

        Search search = new Search();
        search.addSearchFilter("EQ_userBaseId",userBase.getId());
        if (StringUtils.isNotBlank(batchName)) {
            search.addSearchFilter("LIKE_batchName",batchName);
        }

        if (StringUtils.isNotBlank(submitTime)) {
            Integer dt = Integer.valueOf(submitTime.replaceAll("-",""));
            search.addSearchFilter("EQ_submitTimeDt",dt);
        }

        pageNo = pageNo == null ? 0 : pageNo;
        search.addPageRequest(new PageRequest(pageNo,10,new Sort(Sort.Direction.DESC,"id")));
        Page<Batch>  page = batchDao.findPage(search);


        //包装recharge数据
        List<BatchDto> batchDtos = new ArrayList<BatchDto>();
        List<Batch> list = page.getContent();
        for (Batch batch:list) {
            //统计已提交短信数量
            Integer sended = smsrecordService.sended(batch.getId());
            sended = sended == null ? 0 : sended;

            //发送状态 0发送中 1已发送 2等待发送
            Integer sendedStatus = 0;
            if (batch.getTiming() != null) {
                Date now = new Date();
                if (now.getTime() < batch.getTiming().getTime()) {
                    sendedStatus = 2;
                }
            } else {
                if (sended==batch.getTotalNum()) {
                    sendedStatus = 1;
                }
            }
            batch.setSendedStatus(sendedStatus);
            batchDtos.add(SFBeanUtils.injectByObject(new BatchDto(),batch));
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("batchDtos",batchDtos);
        jsonObject.put("totalElements",page.getTotalElements());
        jsonObject.put("size",page.getSize());
        jsonObject.put("totalPages",page.getTotalPages());
        return new JsonResult(0,"ok",jsonObject).toJson(SerializerFeature.WriteMapNullValue);
    }

    @RequestMapping(value = "batch/status")
    @ResponseBody
    public String batchStatus(@RequestParam Long id,@RequestParam Integer status) {
        Batch batch = batchDao.findById(id);
        if (batch!=null) {
            batch.setStatus(status);
            batchDao.update(batch);
            return JsonResult.success("设置成功");
        }
        return JsonResult.create(400,"非法访问");
    }



    /**
     * 发送记录
     */
    @RequestMapping(value = "records")
    @ResponseBody
    public String records(UserBase userBase,String flag,Integer pageNo, String selectApiKey, String createTimeStart, String createTimeEnd, String destAddr){
        JSONObject jsonObject = new JSONObject();
        if ("export".equals(flag)) {
            Date startDate = null;
            Date endDate = null;
            if (StringUtils.isNotBlank(createTimeStart) && StringUtils.isNotBlank(createTimeEnd)) {
                startDate = DateUtils.convertStringToDate(createTimeStart, Constant.FORMAT_YMD_HMS);
                endDate = DateUtils.convertStringToDate(createTimeEnd, Constant.FORMAT_YMD_HMS);
            }
            if (startDate == null || endDate == null) {
                startDate = DateUtils.getSpecficMonthStart(new Date(), -1);
                endDate = DateUtils.getSpecficMonthEnd(new Date(), -1);
            }

            List<FastooMtDetail> list = jdbcTemplateService.findLastMonthRecords(userBase.getLoginName(), startDate, endDate, selectApiKey, destAddr);
            jsonObject.put("list", list);
        } else {
            String today = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
            createTimeStart = Strings.isNullOrEmpty(createTimeStart) ? today + " 00:00:00" : createTimeStart;
            createTimeEnd = Strings.isNullOrEmpty(createTimeEnd) ? today + " 23:59:59" : createTimeEnd;
            Date stime = DateUtils.convertStringToDate(createTimeStart, "yyyy-MM-dd HH:mm:ss");
            Date etime = DateUtils.convertStringToDate(createTimeEnd, "yyyy-MM-dd HH:mm:ss");

            Search search = new Search();
            search.addSearchFilter("EQ_loginName", userBase.getLoginName());
            search.addSearchFilter("GTE_submitTime", stime);
            search.addSearchFilter("LTE_submitTime", etime);
            if (StringUtils.isNotBlank(selectApiKey)) {
                search.addSearchFilter("EQ_apiKey", selectApiKey);
            }
            if (StringUtils.isNotBlank(destAddr)) {
                search.addSearchFilter("EQ_destAddr", destAddr);
            }
            pageNo = pageNo == null ? 0 : pageNo;
            search.addPageRequest(new PageRequest(pageNo, 10, new Sort(Sort.Direction.DESC, "id")));
            Page<FastooMtDetail> page = fastooMtDetailDao.findPage(search);

            //包装recharge数据
            List<SmsrecordDto> smsrecordDtos = new ArrayList<SmsrecordDto>();
            List<FastooMtDetail> list = page.getContent();
            for (FastooMtDetail mtDetail : list) {
                smsrecordDtos.add(SFBeanUtils.injectByObject(new SmsrecordDto(), mtDetail));
            }

            jsonObject.put("selectApiKey", selectApiKey);
            jsonObject.put("createTimeStart", createTimeStart);
            jsonObject.put("createTimeEnd", createTimeEnd);
            jsonObject.put("destAddr", destAddr);
            jsonObject.put("smsrecords", smsrecordDtos);
            jsonObject.put("totalElements", page.getTotalElements());
            jsonObject.put("size", page.getSize());
            jsonObject.put("totalPages", page.getTotalPages());
        }

        return new JsonResult(0,"ok",jsonObject).toJson();
    }

    //导出批次记录
    @RequestMapping(value = "batch/export")
    @ResponseBody
    public String batchExport(Long batchId) {
        JSONObject jsonObject = new JSONObject();
        List<Smsrecord> list = jdbcTemplateService.findRecordsByBatchId(batchId);
        jsonObject.put("list",list);
        return new JsonResult(0,"ok",jsonObject).toJson();
    }

    //导出记录(暂时未用)
    @RequestMapping(value = "records/export")
    @ResponseBody
    public String mtdetailExport(UserBase userBase,String startTime,String endTime,String selectApiKey, String destAddr) {
        JSONObject jsonObject = new JSONObject();
        Date startDate = null;
        Date endDate = null;
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            startDate = DateUtils.convertStringToDate(startTime,Constant.FORMAT_YMD_HMS);
            endDate = DateUtils.convertStringToDate(endTime,Constant.FORMAT_YMD_HMS);
        }
        if (startDate==null||endDate==null) {
            startDate = DateUtils.getSpecficMonthStart(new Date(), -1);
            endDate = DateUtils.getSpecficMonthEnd(new Date(), -1);
        }
//        List<FastooMtDetail> list = jdbcTemplateService.findLastMonthRecords(userBase.getLoginName(),startDate,endDate);
//        jsonObject.put("list",list);
        return new JsonResult(0,"ok",jsonObject).toJson();
    }

    /**
     * 短信快捷发送（单个）
     */
    @RequestMapping(value = "quickSendSingleSms")
    @ResponseBody
    public String quickSendSingleSms(UserBase userBase,UserAccount userAccount, @RequestParam String countryEn,@RequestParam String mobile,
                                      String smscontent,@RequestParam String isDomestic) {

        //1、验证参数是否合法
        if (StringUtils.isBlank(mobile) || "undefined".equals(mobile)) {
            return new JsonResult(201,"手机号码不能为空").toJson();
        }
        if (!RegexUtils.checkPlusDigit(mobile)) {
            return new JsonResult(201,"手机号码格式不准确").toJson();
        }
        if (!"domestic".equals(isDomestic)&&(StringUtils.isBlank(smscontent) || "undefined".equals(smscontent))) {
            return new JsonResult(202,"发送内容不能为空").toJson();
        }

        if ("domestic".equals(isDomestic)) {
            String code = "";
            for (int i = 0;i<4;i++) {
                code += new Random().nextInt(10);
            }
            smscontent = "您的验证码是"+code;
            countryEn = "China";
        }

        //2、发送测试短信
        CountryDict countryDict = countryDictDao.findOne(new Search().addSearchFilter("EQ_nameEn",countryEn));
        if (countryDict == null) {
            return new JsonResult(203,"系统没找到对应国家").toJson();
        }

        // 短信长度
        Integer smNum = MessageHelper.getSmsLength(smscontent,countryDict.getCountrycode(),"");
        Double mtprice = countryDict.getMtprice();
        Double needpay = BigDecimalUtil.mul(mtprice, (double) smNum);
        if (userBase.getBalance() == null || userBase.getBalance() < needpay) {
            return new JsonResult(105,"用户余额不足").toJson();
        }

        try {
            String  result = SmsSender.fastooApiSend(ConfigProps.getFastooApiUrl(),mobile, smscontent,userAccount.getApiKey());
            logger.info("提交结果：userBase="+userBase.getLoginName()+","+result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JsonResult(202,"发送失败").toJson();

    }
    public static void main(String[] args) {
        System.out.println(DateUtils.getSpecficMonthStart(new Date(),-1));
        System.out.println(DateUtils.getSpecficMonthEnd(new Date(),-1));

//        String json = "{\n" +
//                "\"code\": 0,\n" +
//                "\"data\": \"\"" +
//                ",\n" +
//                "\"msg\": \"ok\"\n" +
//                "}";
        String json = "{\n" +
                "\"code\": 0,\n" +
                "\"data\": {\n" +
                "\"vtprice\": 0.15,\n" +
                "\"mtprice\": 0.06\n" +
                "},\n" +
                "\"msg\": \"ok\"\n" +
                "}";
        JSONObject jsonObject = JSON.parseObject(json);

        System.out.println(jsonObject.getString("data"));
        System.out.println("".equals(jsonObject.getString("data")));


    }


}
